/**
 * @file   MyModQuery.java
 * @author Enrique Madrid <e.madrid@lpcsite.com>
 * @date   Fri Sep 21 04:16:11 2007
 *
 * @brief
 *
 *
 */

package sim.query;

import java.lang.*;
import java.util.*;
import javax.microedition.lcdui.*;

import sim.framework.*;
import sim.framework.gui.*;
import sim.framework.io.*;
import sim.framework.dialog.*;
import sim.utils.parser.*;

public abstract class ModQuery extends Module {
    
    // Valores devueltos por las implementaciones de la derivada
    public static final int QUERY_OK = 0;
    public static final int QUERY_STOP = 1;
    public static final int QUERY_IGNORE = 2;
    
    // Variables del GUI
    private static final String TITLE_LABEL = null;
    private static final String BHELP_LABEL = "";
    
    private static final int STATE_SEARCHING = Executable.STATE_USER + 1;
    
    
    private boolean m_Searching = false;
    private boolean m_Stop = false;
    private int m_FirstItem = GuiCtrl.INVALID_ITEM_ID;
    private int m_LastItem = GuiCtrl.INVALID_ITEM_ID;
    
    private GuiCtrlItem m_GuiCtrlItem = new GuiCtrlItem();
    
    protected int m_Step = 10;
    protected boolean m_Multiopt = false;
    
    private DlgQuery m_DlgMain = null;
    private DlgNotify m_DlgShow = null;
    
    private StringBuffer m_TextBuffer = new StringBuffer(64);
    
    public ModQuery(int id, Simlet s) {
        super(id, s);
    }
    
    public ModQuery(int id, Simlet s, boolean multiopt) {
        super(id, s);
        m_Multiopt = multiopt;
    }
    
    public void work( final Msg msg ) {
        switch( msg.getWParam() ) {
	case STATE_INIT:
	    workInit(msg);
	    break;
	case STATE_SEARCHING:
	    workSearching(msg);
	    break;
        }
    }
    
    private void showPopUp(String message) {
        m_DlgMain.popUp(message, m_Simlet.getFontSys().medium);
        m_DlgMain.activeAll(false);
    }
    
    private void hidePopUp() {
        m_DlgMain.popUp_Close();
        m_DlgMain.activeAll(true);
        m_DlgMain.redraw();
    }
    
    private void todoSearching() {
        m_Searching = true;
        todo(STATE_SEARCHING);
    }
    
    private void workInit(final Msg msg) {
        createDlgs();
        setGui(m_DlgMain);
        todoSearching();
    }
    
    private void workSearching(final Msg msg) {
        int i = 0;
        boolean refresh = true;
        
        //#ifdef DEBUG_MODQUERY
        //# System.out.println("ModQuery::workSearching() ENTERED");
        //#endif
        
        showPopUp(getLabel(Resource.LBL_MESG_SEARCHING));
        
        while (m_Searching && !m_Stop && (i < m_Step)) {
            m_GuiCtrlItem.setId(GuiCtrl.INVALID_ITEM_ID);
            switch(querySearch()) {
	    case QUERY_OK:
		//#ifdef DEBUG_MODQUERY
		//# System.out.println("\tModQuery::querySearch() devuelve QUERY_OK");
		//#endif
		if (m_GuiCtrlItem.getId() != GuiCtrl.INVALID_ITEM_ID) {
		    //#ifdef DEBUG_MODQUERY
		    //# System.out.println("\tLa derivada a establecido un nuevo Item");
		    //#endif
		    m_DlgMain.addItem(Dialog.CTRL_MAIN, m_GuiCtrlItem);
		    if (m_FirstItem == GuiCtrl.INVALID_ITEM_ID) {
			m_FirstItem = m_GuiCtrlItem.getId();
		    }
		    m_LastItem = m_GuiCtrlItem.getId();
		    i++;
		}
		//#ifdef DEBUG_MODQUERY
		//# else {
		//# System.out.println("\tLa derivada no ha establecido un Item. ");
		//# }
		//#endif
                    
		break;
	    case QUERY_IGNORE:
		//#ifdef DEBUG_MODQUERY
		//# System.out.println("\tModQuery::querySearch() devuelve QUERY_IGNORE");
		//#endif
		break;
	    case QUERY_STOP:
		//#ifdef DEBUG_MODQUERY
		//# System.out.println("\tModQuery::querySearch() devuelve QUERY_STOP");
		//#endif
		m_Stop = true;
		if (m_DlgMain.getCount(Dialog.CTRL_MAIN) == 0) {
		    refresh = false;
		    showPopUp(getLabel(Resource.LBL_MESG_WITHOUT_RESULTS));
		}
            }
        }
        
        m_Searching = false;
        
        if (refresh) {
            hidePopUp();
        }
        
        //#ifdef DEBUG_MODQUERY
        //# System.out.println("ModQuery::workSearching() EXITING");
        //#endif
        
    }
    
    public boolean event(final Msg msg) {
        boolean ret;
        Gui gui;
        ret = false;
        gui = getGui();
        if (gui.equals(m_DlgMain)) {
            ret = eventMain(msg);
        } else if ((m_DlgShow != null) && (gui.equals(m_DlgShow))) {
            ret = eventShow(msg);
        }
        return ret;
    }
    
    private boolean eventMain(final Msg msg) {
        boolean ret = false;
        
        //#ifdef DEBUG_MODQUERY
        //# System.out.println("ModQuery::eventMain() ENTERED");
        //#endif
        
        if(m_Searching) {
            //#ifdef DEBUG_MODQUERY
            //# System.out.println("\tm_Searching == true");
            //#endif
            switch(msg.getEventCode())   {
	    case EventListener.KEY_PRESSED:
		if(msg.getWParam() == Gui.KEY_CLEAR) {
		    m_Searching = false;
		}
		ret = true;
            }
        } else {
            //#ifdef DEBUG_MODQUERY
            //# System.out.println("\tm_Searching == false");
            //#endif
            switch(msg.getEventCode()) {
	    case EventListener.KEY_RELEASED:
		//#ifdef DEBUG_MODQUERY
		//# System.out.println("\tmsg.getEventCode() = EventListener.KEY_RELEASED");
		//#endif
		switch( msg.getWParam() ) {
		case Gui.KEY_UP:
		case Gui.KEY_DOWN:
		    if (m_DlgMain.getFocusID() == Dialog.CTRL_MAIN) {
			if ((m_DlgMain.getItemId(Dialog.CTRL_MAIN) == m_LastItem) ||
			    (m_DlgMain.getItemId(Dialog.CTRL_MAIN) == m_FirstItem)) {
			    hidePopUp();
			    ret = true;
			}
		    }
		    break;
		case Gui.KEY_STAR:
		case Gui.KEY_POUND:
		    if (m_DlgMain.getFocusID() == Dialog.CTRL_MAIN) {
			hidePopUp();
			ret = true;
		    }
		}
		break;
	    case EventListener.KEY_PRESSED:
		//#ifdef DEBUG_MODQUERY
		//# System.out.println("\tmsg.getEventCode() = EventListener.KEY_PRESSED");
		//#endif
                    
		// Si existiese un popUp abierto se cierra.
		if( m_DlgMain.popUp() ) {
		    // SI GUI ESTUVIERA BIEN DISEÑADO, EL POPUP ESTARÍA CERRADO; PUES,
		    // EL POPUP() SE CIERRA CUANDO SE SUELTA LA TECLA!!!!
		    hidePopUp();
		}
                    
		switch(msg.getWParam()) {
		case Gui.KEY_UP:
		    //#ifdef DEBUG_MODQUERY
		    //# System.out.println("\tmsg.getWParam() = Gui.KEY_UP");
		    //#endif
		    if (m_DlgMain.getFocusID() == Dialog.CTRL_MAIN) {
			if (m_DlgMain.getItemId(Dialog.CTRL_MAIN) == m_FirstItem) {
			    showPopUp(getLabel(Resource.LBL_MESG_BEGIN));
			    //ret = true;
			}
		    }
		    break;
		case Gui.KEY_DOWN:
		    //#ifdef DEBUG_MODQUERY
		    //# System.out.println("\tmsg.getWParam() = Gui.KEY_DOWN");
		    //#endif
		    if (m_DlgMain.getFocusID() == Dialog.CTRL_MAIN) {
			if (m_Stop) {
			    if (m_DlgMain.getItemId(Dialog.CTRL_MAIN) == m_LastItem) {
				showPopUp(getLabel(Resource.LBL_MESG_END));
				//ret = true;
			    }
			} else {
			    if (m_DlgMain.getItemId(Dialog.CTRL_MAIN) == m_LastItem) {
				todoSearching();
				ret = true;
			    }
			}
		    }
		    break;
		case Gui.KEY_STAR:
		    ret = commandInfo(Gui.KEY_STAR);
		    break;
		case Gui.KEY_POUND:
		    ret = commandInfo(Gui.KEY_POUND);
		    break;
		}
		break;
	    case EventListener.COMMAND:
		//#ifdef DEBUG_MODQUERY
		//# System.out.println("\tmsg.getEventCode() = EventListener.COMMAND");
		//#endif
		switch (msg.getWParam()) {
		case Dialog.CTRL_BUTTON_NEXT:
		    ret = commandNext();
		    break;
		case Dialog.CTRL_BUTTON_BACK:
		    ret = commandBack();
		    break;
		case Dialog.CTRL_BUTTON_HELP:
		    // Dont worry be hacker!.
		    ret = commandInfo(Gui.KEY_NONE);
		    break;
		}
            }
        }
        
        //#ifdef DEBUG_MODQUERY
        //# System.out.println("ModQuery::eventMain() EXITING");
        //#endif
        
        return ret;
    }
    
    private boolean commandNext() {
        queryGoToNext();
        return true;
    }
    
    private boolean commandBack() {
        queryGoToBack();
        return true;
    }
    
    private boolean commandInfo(int key) {
        int item;
        // Si el foco lo tiene el control principal, o se hace un hack!...
        if ((m_DlgMain.getFocusID() == Dialog.CTRL_MAIN) || (key == Gui.KEY_NONE)) {
            // Si existe un item seleccionado ...
            item = m_DlgMain.getItemId((Dialog.CTRL_MAIN));
            if (item != GuiCtrl.INVALID_ITEM_ID) {
                // ... borrar el contenido de. buffer temporal
                appendText(null);
                // ... llamar al callback
                switch (key) {
		case Gui.KEY_STAR:
		    queryWhatIs(item);
		    break;
		case Gui.KEY_POUND:
		    queryTellMe(item);
		    break;
		case Gui.KEY_NONE:
		    queryShowMe(item);
		    break;
                }
                // Si se editó en el buffer temporal ...
                if (m_TextBuffer.length() > 0) {
                    // ... mostrarlo en el cuadro en la interfaz gráfica.
                    switch (key) {
		    case Gui.KEY_STAR:
		    case Gui.KEY_POUND:
			showPopUp(m_TextBuffer.toString());
			break;
		    case Gui.KEY_NONE:
			m_DlgShow.setText(Dialog.CTRL_MAIN, m_TextBuffer);
			setGui(m_DlgShow);
                    }
                }
                return true;
            }
        }
        return false;
    }
    
    private boolean eventShow(final Msg msg) {
        boolean ret = false;
        switch (msg.getEventCode()) {
	case EventListener.COMMAND:
	    switch (msg.getWParam()) {
	    case Dialog.CTRL_BUTTON_NEXT:
		setGui(m_DlgMain);
		ret = true;
	    }
        }
        return ret;
    }
    
    private void createDlgs() {
        String showMe;
        
        // Recuperar la etiqueta del boton ?
        showMe = queryShowMeLabel();
        
        // Crear el diálogo principal.
        m_DlgMain = (DlgQuery)DlgQuery.create(m_Simlet,
					      queryTitleLabel(),
					      "",
					      "",
					      queryShowMeLabel(),
					      m_Multiopt);
        // Si se requiere el botón ? ...
        if ((showMe != null) && (m_DlgShow == null)) {
            // Crear el diálogo para mostrar información.
            m_DlgShow = (DlgNotify)DlgNotify.create(m_Simlet,
						    "",
						    null,
						    getLabel(Resource.LBL_CTRL_ACCEPT),
						    null);
        }
    }
    
    
    /**
     * FUCIONES UTILIZADAS POR LOS CALLBACKS.
     *
     */
    
    protected final void setItem(int itemId, final String string,
				 boolean checked, final Image image) {
        m_GuiCtrlItem.setId(itemId);
        m_GuiCtrlItem.setText(string);
        m_GuiCtrlItem.setImage(image);
        m_GuiCtrlItem.setCheck(checked);
    }
    
    protected final void appendText(final String string) {
        // Si el parámetro es nulo ...
        if (string == null) {
            // Borrar el buffer temporal
            m_TextBuffer.setLength(0);
        } else {
            // En caso contrario añadir text
            m_TextBuffer.append(string);
        }
    }
    
    /**
     * METODOS DEFINIDOS Y REDEFINIDOS POR LA CLASE DERIVADA.
     *
     */
    protected abstract int querySearch();
    
    protected void queryGoToNext() {
        execNext();
    }
    
    protected void queryGoToBack() {
        execBack();
    }
    
    protected String queryTitleLabel() {
        return TITLE_LABEL;
    }
    
    protected String queryShowMeLabel() {
        return BHELP_LABEL;
    }
    
    protected void queryWhatIs(int itemId) {
        appendText(null);
    }
    
    protected void queryTellMe(int itemId) {
        appendText(null);
    }
    
    protected void queryShowMe(int itemId) {
        appendText(null);
    }
    
    /**
     * Retorna el ID del primer elemento seleccionado.
     */
    protected final int firstId() {
        return m_DlgMain.getInitId(Dialog.CTRL_MAIN);
    }
    
    /**
     *  Retorna el ID del siguiente elemento seleccionado.
     */
    protected final int nextId() {
        return m_DlgMain.getNextId(Dialog.CTRL_MAIN);
    }
    
}
